package com.example.service.impl;

import com.example.config.ClientConfig;
import com.example.model.bo.GetBigRecord;
import com.example.service.BigFileStoreService;
import com.example.utils.ContractAddressManager;
import com.example.utils.PropertyUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

@Service
@NoArgsConstructor
@Data
public class BigFileStoreServiceImpl implements BigFileStoreService {
    public static final String RegisterAndFileStoreABI = com.example.utils.IOUtil.readResourceAsString("abi/RegisterAndFileStore.abi");
    private String RegisterAndFileStoreAddress = ContractAddressManager.getAddressFromContractNote("RegisterAndFileStore");

    public static final String UserRegistryABI = com.example.utils.IOUtil.readResourceAsString("abi/UserRegistry.abi");
    private String UserRegistryAddress = ContractAddressManager.getAddressFromContractNote("UserRegistry");


    // client 当前版本没有初始化 keypair
    @Autowired
    private Client client;

    AssembleTransactionProcessor txProcessor;

    String clientPri;

    @PostConstruct
    public void init() throws Exception {
        this.txProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(this.client, this.client.getCryptoSuite().getCryptoKeyPair());
    }


    //根据文件名从区块链查询出区块，并且按照顺序排序返回
    @Override
    public List<GetBigRecord> getRecordsByUserNameAndFilename(String filename) throws Exception {
        String userName = PropertyUtil.getUserName();
        AccountManager.loadP12Account(client, ClientConfig.account_keyfile_path + userName, ClientConfig.account_password);
        this.clientPri = client.getCryptoSuite().getCryptoKeyPair().getHexPrivateKey();
        System.out.println("用户的地址+文件名" + client.getCryptoSuite().getCryptoKeyPair().getAddress() + filename);
        List<Object> list = new ArrayList<>();
        list.add(filename);
//        System.out.println("dasdasdasdsadsad");
        CallResponse getRecordsByPrivateKey = this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.RegisterAndFileStoreAddress, RegisterAndFileStoreABI, "getRecordsBySenderandFilename", list);
//        System.out.println("dasdasdasdsadsad");
        List<String> uniqueIds = (List<String>) getRecordsByPrivateKey.getReturnObject().get(0);
        List<List<Object>> files = (List<List<Object>>) getRecordsByPrivateKey.getReturnObject().get(1);
        List<GetBigRecord> res = new ArrayList<>();


        int id = 1;
        for (int i = 0; i < files.size(); i++) {
            List<Object> file = files.get(i);

            String senderAddress = (String) file.get(0);
            String receiverAddress = (String) file.get(1);
            String senderUserName = (String) file.get(2);
            String receiverUserName = (String) file.get(3);
            String filenames = (String) file.get(5);
            String timeStamp = (String) file.get(6);
            String x = (String) file.get(7);

            LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(timeStamp)), ZoneId.systemDefault());
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String formattedDateTime = dateTime.format(formatter);

            String otherUserName = Objects.equals(ClientConfig.account_username, senderUserName) ? receiverUserName : senderUserName;
            List<Object> args = new ArrayList<>();
            args.add(otherUserName);
//            CallResponse getPublicKey = this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.UserRegistryAddress, UserRegistryABI, "getUserPublicKey", args);
//            String otherPublicKey = (String) getPublicKey.getReturnObject().get(0);

            String cid = (String) file.get(4);
//            String cid = ECCUtil.decryptMessage((String) file.get(4), ECCUtil.generateSharedSecret(this.clientPri, otherPublicKey));
            GetBigRecord fileRecord = new GetBigRecord(id++, x, formattedDateTime, filename, cid, senderAddress, receiverAddress, null, senderUserName, receiverUserName);
            res.add(fileRecord);
        }
        Collections.sort(res, ((o1, o2) -> Integer.parseInt(o1.getNumsofblock()) - Integer.parseInt(o2.getNumsofblock())));
        return res;
    }

    @Override
    public boolean blockchainisexit(String filename) throws Exception {
        String userName = PropertyUtil.getUserName();
        AccountManager.loadP12Account(client, ClientConfig.account_keyfile_path + userName, ClientConfig.account_password);
        this.clientPri = client.getCryptoSuite().getCryptoKeyPair().getHexPrivateKey();
        List<Object> list = new ArrayList<>();
        list.add(filename);
        CallResponse getRecordsByPrivateKey = this.txProcessor.sendCall(this.client.getCryptoSuite().getCryptoKeyPair().getAddress(), this.RegisterAndFileStoreAddress, RegisterAndFileStoreABI, "isExist", list);
        boolean isexit = (boolean) getRecordsByPrivateKey.getReturnObject().get(0);
        return isexit;
    }

}
